/**
 * @file EcomCustomerBean.java
 * Projet eCOM 2010 (Miage Descartes)
 * @author Doido Sébastien
 * @version 2
 * @brief Bean relatif au traitement des opérations réalisables par un client (customer)
 */
package ecom.beans;

import ecom.beans.CartBean.CartState;
import ecom.beans.EuroConvertorBean.Currency;
import java.util.Collection;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateful;
import javax.persistence.NoResultException;
import javax.persistence.Query;

/**
 * @brief Bean relatif au traitement des opérations réalisables par un client (customer)
 * @author Sebastien
 */
@Stateful
@Remote(EcomCustomerRemote.class)
public class EcomCustomerBean extends EcomCommonFunctionsBean implements EcomCustomerRemote {

    /**
     * @brief Panier du client
     */
    @EJB
    private CartLocal cart;

    /**
     * @brief Convertisseur monétaire pour le client
     */
    @EJB
    private EuroConvertorRemote convertor;

    /**
     * @brief Ajout d'un produit dans le panier
     * @param productId : produit souhaité
     * @param productStoreId : magasin fournissant le produit
     * @param quantity : quantité commandée
     * @throws ecom.beans.UnknownIdentifier : produit|magasin inexistant
     * @throws ecom.beans.CartException : erreur de panier
     */
    public void addProductToCart(int productId, int productStoreId, int quantity) throws UnknownIdentifier, CartException {
        ProductStoreBean store = this.getStoreById(productStoreId);
        ProductBean product = this.getProductById(productId);

        Query stockList = em.createNamedQuery("getStockByProductAndStore");
        stockList.setParameter("productID", product.getProductId());
        stockList.setParameter("productStoreID", store.getReference());

        try {
            WarehouseLineBean w = (WarehouseLineBean) stockList.getSingleResult();

            if (quantity > w.getQuantity()) {
                throw new CartException("Impossible to order " + quantity + " product #" + productId + " with store #" + productStoreId + " (max : " + w.getQuantity() + ")");
            } else {
                cart.addProduct(w, quantity);
            }
        } catch (NoResultException e) {
            throw new UnknownIdentifier("Store #" + productStoreId + " does not offer product #" + productId);
        }
    }

    /**
     * @brief Supprime un produit du panier
     * @param productId : produit à supprimer
     * @param productStoreId : magasin fournissant le produit
     * @param quantity : quantité à retirer du panier
     * @throws ecom.beans.UnknownIdentifier : produit|magasin inexistant
     * @throws ecom.beans.CartException : erreur panier
     */
    public void removeProductInCart(int productId, int productStoreId, int quantity) throws UnknownIdentifier, CartException {
        ProductStoreBean store = this.getStoreById(productStoreId);
        ProductBean product = this.getProductById(productId);

        Query stockList = em.createNamedQuery("getStockByProductAndStore");
        stockList.setParameter("productID", product.getProductId());
        stockList.setParameter("productStoreID", store.getReference());

        WarehouseLineBean w = (WarehouseLineBean) stockList.getSingleResult();
        cart.removeProduct(w, quantity);
    }

    /**
     * @brief Renvoie les ligne s de commande du panier
     * @return les ligne s de commande du panier
     */
    public Collection<CartLine> getProductsInCart() {
        return cart.getProducts();
    }

    /**
     * @brief Achat du panier pour un compte client
     * @param accountId : référence du compte payeur
     * @throws ecom.beans.UnknownIdentifier : compte inexistant
     * @throws ecom.beans.CartException : erreur panier
     * @return montant total du panier
     */
    public double buyCart(int accountId) throws UnknownIdentifier, CartException {
        AccountBean a = this.getAccountById(accountId);
        double amount = cart.buy(a);

        for(CartLine line : this.getProductsInCart()) {
            WarehouseLineBean stock = line.getStock();
            try {
                System.out.println("Suppression de " + line.getOrderedQuantity());
                this.removeStockLine(stock.getStore().getReference(), stock.getProduct().getProductId(), line.getOrderedQuantity());
            } catch (Exception ex) {
                Logger.getLogger(EcomCustomerBean.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        cart.emptyCart();
        return amount;
    }

    /**
     * @brief Renvoie le montant total du panier
     * @return le montant total du panier
     */
    public double getCartTotalPrice() {
        return cart.getTotalPrice();
    }

    /**
     * @brief Renvoie l'état du panier
     * @return l'état du panier
     */
    public CartState getCartState() {
        return cart.getState();
    }

    // Convertor stuff
    /**
     * @brief Renvoie une devise monétaire pour un code devise donné
     * @param valueOf : code devise
     * @return une devise monétise pour un code devise donné
     * @throws java.lang.Exception : code devise inexistant
     */
    public Currency getCurrencyByName(String valueOf) throws Exception {
        return Currency.get(valueOf);
    }
    
    /**
     * @brief Renvoie la liste des devises monétaires connues
     * @return la liste des devises monétaires connues
     */
    public Vector<String> getCurrencySymbols() {
        return convertor.getCurrencySymbols();
    }


    /**
     * @brief Renvoie le nom complet d'une devise monétaire pour un code devise donné
     * @param valueOf : code devise
     * @return le nom complet d'une devise monétaire pour un code devise donné
     * @throws java.lang.Exception : code devise inexistant
     */
    public String getCurrencyRealName(String valueOf) throws Exception {
        return convertor.getCurrencyRealName(valueOf);
    }

    /**
     * @brief Convertit un montant en euro vers un montant de devise X
     * @param amount : montant à couvertir
     * @param currencySymbol : devise de destination
     * @return
     */
    public double convertFromEuro(double amount, String currencySymbol) {
        return convertor.convertFromEuro(amount, currencySymbol);
    }

    /**
     * @brief Convertit un montant d'une devise vers un montant en euro
     * @param amount : montant à convertir
     * @param currencySymbol : devise d'origine
     * @return le montant converti
     */
	public double convertToEuro(double amount, String currencySymbol) {
        return convertor.convertToEuro(amount, currencySymbol);
    }

    /**
     * @brief Depot d'argent sur un compte client
     * @param accountId : compte à créditer
     * @param amount : montant à déposer
     * @throws ecom.beans.UnknownIdentifier : compte inexistant
     */
    public void deposit(int accountId, double amount) throws UnknownIdentifier {
        System.out.println("deposit bean :" + accountId);
        AccountBean a = this.getAccountById(accountId);
        a.deposit(amount);
    }
}
